package james.gan.config.spring.bean;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import james.gan.common.Request;
import james.gan.config.spring.annotation.RpcCustom;

//@Component
public class CustomBeanPostProcessor implements BeanPostProcessor, BeanFactoryPostProcessor {

	private ConfigurableListableBeanFactory beListableBeanFactory;
	private static final List<String> customsNames  = new CopyOnWriteArrayList<>();

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		Field[] fields = bean.getClass().getDeclaredFields();

		for (Field f : fields) {
			RpcCustom[] customs = f.getAnnotationsByType(RpcCustom.class);
			if (customs.length == 0) {
				break;
			}
			customsNames.add(beanName);
			RpcCustom custom = customs[0];
			Class<?> type = f.getType();
			Object proxyInstance = proxyCustom(custom, type);
			beListableBeanFactory.registerSingleton(f.getName(), proxyInstance);
			beListableBeanFactory.autowireBean(bean);
			
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
	
	public Object proxyCustom(RpcCustom custom, Class<?> clz) {
		String value = custom.value();
		return Proxy.newProxyInstance(clz.getClassLoader(), new Class<?>[] { clz }, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				Request request = new Request();
				request.setId(UUID.randomUUID().toString());
				request.setMethodName(method.getName());
				request.setParameterTypes(method.getParameterTypes());
				request.setClassName(method.getDeclaringClass());
				request.setParameters(args);
				return "1234";
			}
		});
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		beListableBeanFactory = beanFactory;
	}
}
